/**
 * @file TTS
 * @module libs/tts
 * @author 月落 <yueluo.yang@qq.com>
 */

/**
 * @requires ws - websocket模块
 * @requires requst - 请求库
 * @requires fs - 文件读写模块
 * @requires qs - 格式化数据
 */
const WebSokcet = require('ws'),
      request = require('request'),
      fs = require('fs'),
      qs = require('qs');

/**
 * @requires config/config - 基础配置
 * @requires config/secret - 秘钥
 * @requires libs/tools - 工具方法
 */
const { domains, outputs, hosts } = require('../config/config'),
      { aliSecret } = require('../config/secret'),
      { getAuthStr, composeData, saveFile } = require('./tools');

/**
 * @description 阿里TTS
 * @param {string} id - 故事ID
 * @param {string} text - 文字
 * @param {string} d_t - 用户凭证
 * @returns {promise}
 */
const aliTTS = ({ d_t, text, id }) => {
  return new Promise((resolve, reject) => {
    const content = {
      appkey: aliSecret.appkey,
      token: d_t,
      text,
      format: 'wav',
      sample_rate: 16000
    };

    request({
      url: `${domains.aliDomain}/stream/v1/tts`,
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(content),
      encoding: null
    }, (error, response, body) => {
      if (error != null) {
        console.log(error);
        return;
      } 
      
      const contentType = response.headers['content-type'];

      if (contentType === undefined || contentType != 'audio/mpeg') {
        console.log(body.toString());
        console.log('The POST request failed!');
      } else {
        fs.writeFileSync(`${outputs.wavSavePath}/${id}.wav`, body);

        console.log('The POST request is succeed!');
      }

      resolve(`${domains.baseDomain}/${id}.wav`);
    });
  });
}

/**
 * @description 讯飞TTS
 * @param {string} id - 故事ID
 * @param {string} text - 文字
 * @param {string} format - 文件格式
 * @returns {promise}
 */
const xfyunTTS = ({ text, id, format = 'mp3' }) => {
  return new Promise((resolve, reject) => {
    const date = new Date().toUTCString(),
        _tts = '/v2/tts';
        
    const params = {
      authorization: getAuthStr(date, _tts),
      date,
      host: hosts.xfyunHost
    };

    const wssUrl = `${domains.xfyunDomain}${_tts}?${qs.stringify(params)}`;
    const ws = new WebSokcet(wssUrl);

    ws.on('open', () => {
      console.log('websocket connect.');
      // 发送数据
      ws.send(composeData({
        vcn: 'x2_yifei',
        speed: 38,
        format,
        text
      }));
    });

    ws.on('message', (res, err) => {
      if (err) {
        console.log(`message error ${err}`);
        return;
      }

      const { code, message, data } = JSON.parse(res);

      if (code !== 0) {
        console.log(`${code} ${message}`);
        ws.close();
        return;
      }

      const audioBuf = Buffer.from(data.audio, 'base64'),
            filename = `${id}.${format}`;


      // 保存文件到本地
      saveFile({
        path: `${outputs.wavSavePath}/${filename}`,
        data: audioBuf
      })
        .then(resolve(`${domains.baseDomain}/${filename}`))
        .catch(reject);

      if (code === 0 && data.status === 2) {
        ws.close();
      }
    });

    ws.on('close', () => {
      console.log('connect close.');
    });

    ws.on('error', (err) => {
      reject(err);
      console.log(`websocket connect err：${err}`);
    });
  });
}

// 导出TTS
module.exports = {
  ali: aliTTS,
  xfyun: xfyunTTS
}